<template>
  <div class="editor-container flex">
    <div v-if="editor" class="menu-bar w-[200px]">
      <div class="block-menu-header">工具栏</div>
      <div v-for="block in blockTypes" :key="block.type" class="block-menu-item" :class="{ 'is-active': block.isActive && block.isActive(editor) }" @click="insertBlock(block)">
        <div class="block-icon">{{ block.icon }}</div>
        <div class="block-details">
          <div class="block-title">{{ block.title }}</div>
          <div class="block-description">{{ block.description }}</div>
        </div>
      </div>
    </div>
    <!-- 气泡菜单（选中文本时出现） -->
    <BubbleMenu class="bubble-menu" :editor="editor" :tippy-options="{ duration: 100 }" v-if="editor">
      <button @click="editor.chain().focus().toggleHeading({ level: 1 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 1 }) }">H1</button>
      <button @click="editor.chain().focus().toggleHeading({ level: 2 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 2 }) }">H2</button>
      <button @click="editor.chain().focus().toggleHeading({ level: 3 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 3 }) }">H3</button>
      <button @click="editor.chain().focus().toggleHeading({ level: 4 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 4 }) }">H4</button>
      <!-- <button @click="editor.chain().focus().toggleHeading({ level: 5 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 5 }) }">H5</button>
      <button @click="editor.chain().focus().toggleHeading({ level: 6 }).run()" :class="{ 'is-active': editor.isActive('heading', { level: 6 }) }">H6</button> -->
      <button @click="editor.chain().focus().toggleBold().run()" :class="{ 'is-active': editor.isActive('bold') }">
        <strong>B</strong>
      </button>
      <button @click="editor.chain().focus().toggleItalic().run()" :class="{ 'is-active': editor.isActive('italic') }">
        <em>I</em>
      </button>
      <button @click="openLinkDialog" :class="{ 'is-active': editor.isActive('link') }">🔗</button>
      <button @click="editor.chain().focus().setTextAlign('left').run()" :class="{ 'is-active': editor.isActive({ textAlign: 'left' }) }">←</button>
      <button @click="editor.chain().focus().setTextAlign('center').run()" :class="{ 'is-active': editor.isActive({ textAlign: 'center' }) }">中</button>
      <button @click="editor.chain().focus().setTextAlign('right').run()" :class="{ 'is-active': editor.isActive({ textAlign: 'right' }) }">→</button>
    </BubbleMenu>

    <!-- 编辑器内容区域 -->
    <EditorContent :editor="editor" class="editor-content het-panel" />

    <!-- 链接对话框 -->
    <el-dialog v-model="linkDialogVisible" title="添加链接" width="500px">
      <el-form :model="linkForm" label-width="80px">
        <el-form-item label="链接地址">
          <el-input v-model="linkForm.href" placeholder="请输入URL (如 https://example.com)" />
        </el-form-item>
        <el-form-item label="显示文本">
          <el-input v-model="linkForm.text" placeholder="请输入链接显示文本" />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="linkDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="insertLink">确认</el-button>
      </template>
    </el-dialog>

    <!-- 图表插入对话框 -->
    <el-dialog v-model="chartDialogVisible" title="插入图表" width="800px">
      <el-tabs v-model="activeChartTab">
        <el-tab-pane label="柱状图" name="bar">
          <div ref="barChart" style="width: 100%; height: 400px"></div>
        </el-tab-pane>
        <el-tab-pane label="折线图" name="line">
          <div ref="lineChart" style="width: 100%; height: 400px"></div>
        </el-tab-pane>
        <el-tab-pane label="饼图" name="pie">
          <div ref="pieChart" style="width: 100%; height: 400px"></div>
        </el-tab-pane>
      </el-tabs>

      <template #footer>
        <el-button @click="chartDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="insertChart">插入</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount, nextTick } from 'vue'
import { Editor, useEditor, EditorContent, FloatingMenu, BubbleMenu } from '@tiptap/vue-3'
import { Extension } from '@tiptap/core'
import StarterKit from '@tiptap/starter-kit'
import Document from '@tiptap/extension-document'
import Heading from '@tiptap/extension-heading'
import Image from '@tiptap/extension-image'
import ListItem from '@tiptap/extension-list-item'
import OrderedList from '@tiptap/extension-ordered-list'
import BulletList from '@tiptap/extension-bullet-list'
import TaskList from '@tiptap/extension-task-list'
import TaskItem from '@tiptap/extension-task-item'
import Placeholder from '@tiptap/extension-placeholder'
import Paragraph from '@tiptap/extension-paragraph'
import Text from '@tiptap/extension-text'
import CodeBlockLowlight from '@tiptap/extension-code-block-lowlight'
import Blockquote from '@tiptap/extension-blockquote'
import HorizontalRule from '@tiptap/extension-horizontal-rule'
import Highlight from '@tiptap/extension-highlight'
import Link from '@tiptap/extension-link'
import TextAlign from '@tiptap/extension-text-align'
// import { CustomTable } from './Table.js'
import CustomTable from './CustomTable'
import { all, createLowlight } from 'lowlight'
import * as echarts from 'echarts'

const lowlight = createLowlight(all)
const linkDialogVisible = ref(false)
const linkForm = ref({
  href: '',
  text: ''
})
// 自定义图表节点扩展
const Chart = Image.extend({
  name: 'chart',
  addAttributes() {
    return {
      ...this.parent?.(),
      type: {
        default: 'bar'
      },
      data: {
        default: null
      },
      width: {
        default: '100%'
      },
      height: {
        default: '400px'
      },
      isChart: {
        default: true
      }
    }
  },
  // 添加命令
  addCommands() {
    return {
      setChart:
        options =>
        ({ commands }) => {
          return commands.insertContent({
            type: this.name,
            attrs: options
          })
        }
    }
  },
  renderHTML({ HTMLAttributes }) {
    if (HTMLAttributes.isChart) {
      // 创建一个容器用于渲染图表
      return [
        'div',
        {
          class: 'chart-container',
          'data-type': HTMLAttributes.type,
          'data-data': JSON.stringify(HTMLAttributes.data),
          style: `width: ${HTMLAttributes.width}; height: ${HTMLAttributes.height};`
        }
      ]
    }
    // 默认图片渲染
    return this.parent?.(HTMLAttributes) || ['img', HTMLAttributes]
  }
})
// 定义可插入的块类型
const blockTypes = ref([
  {
    type: 'paragraph',
    title: '文本',
    description: '普通文本段落',
    icon: 'T',
    isActive: editor => editor.isActive('paragraph'),
    command: editor => editor.chain().focus().setParagraph().run()
  },
  {
    type: 'heading',
    title: '标题',
    description: '标题',
    icon: 'H',
    isActive: editor => editor.isActive('heading', { level: 1 }),
    command: editor => editor.chain().focus().toggleHeading({ level: 1 }).run()
  },
  {
    type: 'chart',
    title: '图表',
    description: '图表',
    icon: '💫',
    isActive: editor => editor.isActive('chart'),
    command: editor => openChartDialog()
  },
  {
    type: 'table',
    title: '表格',
    description: '表格',
    icon: '💫',
    isActive: editor => editor.isActive('customTable'),
    command: editor => insertTable(editor)
  },
  {
    type: 'bulletList',
    title: '无序列表',
    description: '简单的项目符号列表',
    icon: '•',
    isActive: editor => editor.isActive('bulletList'),
    command: editor => editor.chain().focus().toggleBulletList().run()
  },
  {
    type: 'orderedList',
    title: '有序列表',
    description: '带编号的列表',
    icon: '1.',
    isActive: editor => editor.isActive('orderedList'),
    command: editor => editor.chain().focus().toggleOrderedList().run()
  },
  {
    type: 'taskList',
    title: '任务列表',
    description: '带复选框的任务列表',
    icon: '✓',
    isActive: editor => editor.isActive('taskList'),
    command: editor => editor.chain().focus().toggleTaskList().run()
  },
  {
    type: 'image',
    title: '图片',
    description: '上传或嵌入图片',
    icon: '🖼️',
    command: async editor => {
      const url = window.prompt('输入图片URL')
      if (url) {
        editor.chain().focus().setImage({ src: url }).run()
      }
    }
  },
  {
    type: 'code',
    title: '代码块',
    description: '带有语法高亮的代码',
    icon: '</>',
    isActive: editor => editor.isActive('codeBlock'),
    command: editor => editor.chain().focus().toggleCodeBlock().run()
  },
  {
    type: 'quote',
    title: '引用',
    description: '引用文本',
    icon: '❝',
    isActive: editor => editor.isActive('blockquote'),
    command: editor => editor.chain().focus().toggleBlockquote().run()
  },
  {
    type: 'divider',
    title: '分割线',
    description: '视觉分隔线',
    icon: '―',
    command: editor => editor.chain().focus().setHorizontalRule().run()
  }
])

// 插入块
const insertBlock = block => {
  block.command(editor.value)
  // showBlockMenu.value = false;
}
const insertTable = editor => {
  editor
    .chain()
    .focus()
    .insertCustomTable({
      data: [
        { date: '', name: '', address: '' },
        { date: '', name: '', address: '' }
      ]
    })
    .run()
}
const openLinkDialog = () => {
  // 如果已选中文本，使用选中文本作为默认显示文本
  const { from, to, empty } = editor.value.state.selection
  if (!empty) {
    linkForm.value.text = editor.value.state.doc.textBetween(from, to, ' ')
  } else {
    linkForm.value.text = ''
  }

  // 检查当前是否在链接中
  if (editor.value.isActive('link')) {
    const attrs = editor.value.getAttributes('link')
    linkForm.value.href = attrs.href
    if (!linkForm.value.text) {
      linkForm.value.text = attrs.href
    }
  } else {
    linkForm.value.href = ''
  }
  linkDialogVisible.value = true
}
const insertLink = () => {
  // 如果没有输入显示文本，则使用链接地址作为显示文本
  const text = linkForm.value.text || linkForm.value.href

  editor.value
    .chain()
    .focus()
    // 先取消已有链接
    .unsetLink()
    // 创建新链接
    .setLink({ href: linkForm.value.href })
    // 插入或替换文本
    .insertContent({
      type: 'text',
      text: text,
      marks: [
        {
          type: 'link',
          attrs: {
            href: linkForm.value.href,
            target: '_blank' // 可选：在新标签页打开
          }
        }
      ]
    })
    .run()
  // 关闭对话框并重置表单
  linkDialogVisible.value = false
  linkForm.value = { href: '', text: '' }
}

let editor = useEditor({
  autofocus: true,
  extensions: [
    StarterKit,
    Chart,
    Document,
    BulletList,
    OrderedList,
    ListItem,
    Paragraph,
    Text,
    TextAlign.configure({
      types: ['heading', 'paragraph']
    }),
    // Heading.configure({
    //   levels: [1, 2, 3],
    // }),
    // Image.configure({
    //   inline: true,
    //   allowBase64: true,
    // }),
    TaskList.configure({
      HTMLAttributes: {
        class: 'task-list'
      }
    }),
    TaskItem.configure({
      nested: true
    }),
    CodeBlockLowlight.configure({
      lowlight
    }),
    Link.configure({
      // openOnClick: false, // 禁用点击链接时打开
      HTMLAttributes: {
        class: 'custom-link' // 自定义链接类名
      }
    }),
    CustomTable
    // Blockquote,
    // HorizontalRule,
    // Placeholder.configure({
    //   placeholder: '输入 "/" 查看命令...',
    // }),
  ],
  content: `
    
  `,
  onUpdate: ({ editor }) => {
    updateLineHighlight()
    renderCharts()
  },
  onSelectionUpdate: ({ editor }) => {
    updateLineHighlight()
  },
  onBlur: () => {
    document.querySelectorAll('.editor-content .current-line').forEach(el => {
      el.classList.remove('current-line')
    })
  },
  onFocus: () => {
    updateLineHighlight()
  }
})
const updateLineHighlight = () => {
  const editorDom = document.querySelector('.editor-content')
  if (!editor.value || !editorDom) return

  // // 移除旧高亮
  // editorDom.querySelectorAll(".current-line").forEach((el) => {
  //   el.classList.remove("current-line");
  // });

  // 获取当前行DOM元素
  const pos = editor.value.state.selection.$from
  const node = editor.value.view.domAtPos(pos.pos).node

  // 向上查找行级元素（p, li等）
  let lineElement = node

  while (lineElement && !['LI', 'DIV'].includes(lineElement.tagName) && lineElement.parentElement) {
    lineElement = lineElement.parentElement
  }
  // 添加新高亮
  if (lineElement && lineElement.closest('.editor-content')) {
    lineElement.classList.add('current-line')
  }
}
// 图表对话框相关状态
const chartDialogVisible = ref(false)
const activeChartTab = ref('bar')
const barChart = ref(null)
const lineChart = ref(null)
const pieChart = ref(null)

// 示例图表数据
const chartData = {
  bar: {
    categories: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
    series: [120, 200, 150, 80, 70, 110, 130]
  },
  line: {
    categories: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
    series: [820, 932, 901, 934, 1290, 1330, 1320]
  },
  pie: {
    categories: ['Direct', 'Email', 'Ad Networks', 'Video Ads', 'Search Engines'],
    series: [
      { value: 335, name: 'Direct' },
      { value: 310, name: 'Email' },
      { value: 234, name: 'Ad Networks' },
      { value: 135, name: 'Video Ads' },
      { value: 1548, name: 'Search Engines' }
    ]
  }
}
// 图表实例
let barChartInstance = null
let lineChartInstance = null
let pieChartInstance = null

// 打开图表对话框
const openChartDialog = () => {
  chartDialogVisible.value = true
  nextTick(() => {
    initCharts()
  })
}
// 初始化图表
const initCharts = () => {
  // 销毁旧实例
  if (barChartInstance) barChartInstance.dispose()
  if (lineChartInstance) lineChartInstance.dispose()
  if (pieChartInstance) pieChartInstance.dispose()

  // 初始化柱状图
  if (barChart.value) {
    barChartInstance = echarts.init(barChart.value)
    barChartInstance.setOption({
      title: { text: '柱状图示例' },
      tooltip: {},
      xAxis: { data: chartData.bar.categories },
      yAxis: {},
      series: [{ name: '销量', type: 'bar', data: chartData.bar.series }]
    })
  }
  // 初始化折线图
  if (lineChart.value) {
    lineChartInstance = echarts.init(lineChart.value)
    lineChartInstance.setOption({
      title: { text: '折线图示例' },
      tooltip: {},
      xAxis: { type: 'category', data: chartData.line.categories },
      yAxis: { type: 'value' },
      series: [{ data: chartData.line.series, type: 'line' }]
    })
  }
  // 初始化饼图
  if (pieChart.value) {
    pieChartInstance = echarts.init(pieChart.value)
    pieChartInstance.setOption({
      title: { text: '饼图示例' },
      tooltip: { trigger: 'item' },
      legend: { orient: 'vertical', left: 'left' },
      series: [
        {
          name: '访问来源',
          type: 'pie',
          radius: '50%',
          data: chartData.pie.series,
          emphasis: { itemStyle: { shadowBlur: 10, shadowOffsetX: 0, shadowColor: 'rgba(0, 0, 0, 0.5)' } }
        }
      ]
    })
  }
}
// 插入图表
const insertChart = () => {
  const selectedData = chartData[activeChartTab.value]

  editor.value
    .chain()
    .focus()
    .setChart({
      type: activeChartTab.value,
      data: selectedData,
      width: '100%',
      height: '400px',
      isChart: true
    })
    .run()

  chartDialogVisible.value = false
}
// 渲染编辑器中的图表
const renderCharts = () => {
  if (!editor.value) return

  nextTick(() => {
    const chartContainers = document.querySelectorAll('.chart-container')
    chartContainers.forEach(container => {
      const type = container.getAttribute('data-type')
      const data = JSON.parse(container.getAttribute('data-data'))

      // 如果已经有图表实例，先销毁
      const existingInstance = echarts.getInstanceByDom(container)
      if (existingInstance) {
        existingInstance.dispose()
      }

      // 初始化新图表
      const chartInstance = echarts.init(container)

      // 根据类型设置不同的图表选项
      let option = {}
      switch (type) {
        case 'bar':
          option = {
            title: { text: '柱状图' },
            tooltip: {},
            xAxis: { data: data.categories },
            yAxis: {},
            series: [{ name: '数据', type: 'bar', data: data.series }]
          }
          break
        case 'line':
          option = {
            title: { text: '折线图' },
            tooltip: {},
            xAxis: { type: 'category', data: data.categories },
            yAxis: { type: 'value' },
            series: [{ data: data.series, type: 'line' }]
          }
          break
        case 'pie':
          option = {
            title: { text: '饼图' },
            tooltip: { trigger: 'item' },
            legend: { orient: 'vertical', left: 'left' },
            series: [
              {
                name: '数据',
                type: 'pie',
                radius: '50%',
                data: data.series,
                emphasis: { itemStyle: { shadowBlur: 10, shadowOffsetX: 0, shadowColor: 'rgba(0, 0, 0, 0.5)' } }
              }
            ]
          }
          break
      }

      chartInstance.setOption(option)
      // 窗口大小变化时重新调整图表大小
      const resizeObserver = new ResizeObserver(() => {
        chartInstance.resize()
      })
      resizeObserver.observe(container)
    })
  })
}
onMounted(() => {
  renderCharts()
})

onBeforeUnmount(() => {})
</script>

<style scoped lang="scss">
.editor-container {
  width: 80%;
  margin: 0 auto;
  justify-content: space-between;
}
.menu-bar {
  background: #fff;
  border-radius: 8px;
  max-height: 665px;
}
.editor-content {
  width: calc(100% - 210px);
  min-height: 500px;
}

/* 浮动菜单样式 */
.floating-menu {
  position: absolute;
  z-index: 10;
}

.floating-menu-button {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background-color: #fff;
  border: 1px solid #e0e0e0;
  color: #666;
  font-size: 16px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all 0.2s;
}

.floating-menu-button:hover {
  background-color: #f5f5f5;
}

/* 块选择器菜单样式 */
.block-menu {
  width: 280px;
  background: #fff;
  border-radius: 8px;
  box-shadow: 0 5px 20px rgba(0, 0, 0, 0.1);
  padding: 8px;
  margin-left: 10px;
}

.block-menu-header {
  padding: 8px 12px;
  font-size: 12px;
  color: #999;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

.block-menu-item {
  display: flex;
  align-items: center;
  padding: 8px 12px;
  border-radius: 4px;
  cursor: pointer;
}

.block-menu-item:hover {
  background-color: #f5f5f5;
}

.block-icon {
  width: 36px;
  height: 36px;
  border-radius: 4px;
  background-color: #f0f0f0;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-right: 12px;
  font-size: 14px;
}

.block-details {
  flex: 1;
}

.block-title {
  font-weight: 500;
  font-size: 14px;
}

.block-description {
  font-size: 12px;
  color: #999;
  margin-top: 2px;
}

/* 气泡菜单样式 */
.bubble-menu {
  display: flex;
  background-color: #fff;
  border: 1px solid #e0e0e0;
  border-radius: 6px;
  padding: 4px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}

.bubble-menu button {
  padding: 4px 8px;
  margin: 0 2px;
  border: none;
  background: none;
  border-radius: 4px;
  cursor: pointer;
}

.is-active {
  background-color: #e0e0e0 !important;
}

/* 编辑器内容样式 */
:deep(.ProseMirror) {
  outline: none;
  blockquote {
    padding-left: 1rem;
    border-left: 3px solid #e0e0e0;
    margin-left: 0;
    margin-right: 0;
  }
  pre {
    background: black;
    border-radius: 0.5rem;
    color: white;
    font-family: 'JetBrainsMono', monospace;
    margin: 1.5rem 0;
    padding: 0.75rem 1rem;
    code {
      background: none;
      color: inherit;
      font-size: 0.8rem;
      padding: 0;
    }
  }
  hr {
    border: none;
    border-top: 2px solid #e0e0e0;
    margin: 2rem 0;
  }
  img {
    max-width: 100%;
    height: auto;
  }
  ol,
  ul {
    list-style: auto;
    padding-left: 2rem;
    li::marker {
      unicode-bidi: isolate;
      font-variant-numeric: tabular-nums;
      text-transform: none;
      text-indent: 0px !important;
      text-align: start !important;
      text-align-last: auto !important;
    }
  }
  ul {
    list-style-type: disc;
  }
  ol {
    list-style-type: decimal;
  }
  .task-list {
    list-style-type: none;
    list-style: none;
    li {
      display: flex;
      align-items: center;
      input[type='checkbox'] {
        margin-right: 5px;
      }
    }
  }
}
// :deep(.ProseMirror pre) {
//   background: black;
//   border-radius: 0.5rem;
//   color: white;
//   font-family: "JetBrainsMono", monospace;
//   margin: 1.5rem 0;
//   padding: 0.75rem 1rem;
//   code {
//     background: none;
//     color: inherit;
//     font-size: 0.8rem;
//     padding: 0;
//   }
// }

// .ProseMirror .task-item {
//   display: flex;
//   align-items: center;
// }

// .ProseMirror .task-item input[type="checkbox"] {
//   margin-right: 0.5rem;
// }
/* 高亮样式 */
.highlighted-line {
  background-color: #f0f7ff;
  border-radius: 3px;
}
:deep(.current-line) {
  background-color: #f0f7ff; /* 浅蓝色背景 */
  border-radius: 3px;
}
:deep(.el-overlay) {
  z-index: 12000 !important;
}
:deep(.tippy-box) {
  max-width: none !important;
}
</style>
